import { Token, TokenType } from "../token/token";

// 定义抽象语法结构树的基础节点接口
export interface Node {
    tokenLiteral(): string;
    toString(): string;//这里添加toString()方法，能够简化后续的工作。该方法既可以在调试时打印AST节点，也可以用来比较ast节点，这在测试中非常方便
}
// 定义语句接口，继承node接口
export interface Statement extends Node {
    statementNode(): void;
}
// 定义表达式接口，继承node接口
export interface Expression extends Node {
    expressionNode(): void;
}

//这个program节点将成为语法分析器生成的每个ast的根节点。每个有效的monkey程序都是一系列位于Program.Statement中的语句。
export class Program implements Node{

    statements : Statement[] ;

    constructor() {
        this.statements = [];
    }

    public tokenLiteral(): string {
        if (this.statements.length > 0){
            return this.statements[0].tokenLiteral();
        }else{
            return '';
        }
        
    }

    public toString(): string {
        let out = Buffer.alloc(256);
        for(let i = 0; i < this.statements.length; i++){
            out.write(this.statements[i].toString(), i * 256);
        }
        return out.toString();
    }

}

export class Identifier implements Expression {
    public token: Token;
    public value: string;

    constructor(token: Token, value: string) {
        this.token = token;
        this.value = value;
    }
    public expressionNode(): void {}
    public tokenLiteral(): string {
        return this.token.literal;
    }

    public toString(): string{
        return this.value;
    }
}

//定义let语法结构
export class LetStatement implements Statement { 
    public token: Token | null = null; //token.let词法单元
    public name: Identifier | null = null; //标识符
    public value: Expression | null = null; //表达式

    constructor(token: Token | null) {
        this.token = token;
    }


    public statementNode(): void {}

    public tokenLiteral(): string {
        return this.token ? this.token.literal : '';
    }

    public toString(): string {
        let out = Buffer.alloc(256);
        out.write(this.tokenLiteral()+' ');
        out.write(this.name? this.name.toString() : '');
        out.write( ' = ');
        out.write(this.value? this.value.toString() : '');
        out.write(';');
        return out.toString();
    }
}

//定义return语法结构
export class ReturnStatement implements Statement{
    public token: Token | null = null;//token.reaturn词法单元
    public value: Expression | null = null;

    constructor(token: Token | null){
        this.token = token;
    }

    public statementNode(): void {}

    public tokenLiteral(): string {
        return this.token ? this.token.literal : '';
    }

    public toString(): string {
        let out = Buffer.alloc(236);
        out.write(this.tokenLiteral()+' ');
        out.write(this.value ? this.value.toString() : '');
        return out.toString();
    }
}

export class IfStatement implements Statement{
    public token: Token | null = null;//token.reaturn词法单元
    public value: Expression | null = null;

    constructor(token: Token | null){
        this.token = token;
    }

    public statementNode(): void {}

    public tokenLiteral(): string {
        return this.token ? this.token.literal : '';
    }
}

export class ExpressionStatement implements Statement{
    private token: Token | null;
    private expression: Expression | null = null;

    constructor(token: Token | null){
        this.token = token;
    }
    public statementNode(): void {
        
    }

    public tokenLiteral(): string {
        return this.token?.literal || '';
    }

    public toString(): string {
        return this.expression ? this.expression.toString() : '';
    }
}